package app.server.project.main.service.service.auth.tg;

import cn.hutool.json.JSONUtil;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.time.Instant;
import java.util.*;


public class TelegramMiniAppVerifier {

    private static final String HMAC_ALGORITHM = "HmacSHA256";
    private static final long MAX_TIME_DELTA_SECONDS = 86400; // 24小时，根据需要调整

    /**
     * 验证电报Mini App的initData签名
     *
     * @param initData 从客户端获取的initData字符串
     * @param botToken 你的电报Bot Token
     * @return 验证结果
     */
    public static VerificationResult verify(String initData, String botToken) {
        try {
            // 解析initData为Map
            Map<String, String> data = parseInitData(initData);

            // 提取签名和时间戳
            String providedHash = data.remove("hash");
            String authDateStr = data.get("auth_date");

            if (providedHash == null || authDateStr == null) {
                return VerificationResult.failure("Missing 'hash' or 'auth_date' parameter");
            }

            // 验证时间戳有效性
            long authDate = Long.parseLong(authDateStr);
            if (!isTimestampValid(authDate)) {
                return VerificationResult.failure("Timestamp is invalid or too old");
            }

            // 生成预期的哈希值
            String expectedHash = generateDataHash(data, botToken);

            // 比较哈希值
            if (!providedHash.equals(expectedHash)) {
                return VerificationResult.failure("Hash mismatch, data may have been tampered with");
            }

            return VerificationResult.success(data);
        } catch (Exception e) {
            return VerificationResult.failure("Verification error: " + e.getMessage());
        }
    }

    /**
     * 解析initData字符串为键值对Map
     */
    private static Map<String, String> parseInitData(String initData) {
        Map<String, String> result = new HashMap<>();
        if (initData == null || initData.isEmpty()) {
            return result;
        }

        String[] params = initData.split("&");
        for (String param : params) {
            String[] keyValue = param.split("=", 2);
            if (keyValue.length == 2) {
                try {
                    String key = URLDecoder.decode(keyValue[0], StandardCharsets.UTF_8.name());
                    String value = URLDecoder.decode(keyValue[1], StandardCharsets.UTF_8.name());
                    result.put(key, value);
                } catch (Exception e) {
                    // 忽略解析错误的参数
                }
            }
        }
        return result;
    }

    /**
     * 生成数据的哈希值
     */
    private static String generateDataHash(Map<String, String> data, String botToken)
            throws NoSuchAlgorithmException, InvalidKeyException {
        // 按字母顺序排序参数
        List<String> sortedKeys = new ArrayList<>(data.keySet());
        Collections.sort(sortedKeys);

        // 连接排序后的参数
        StringBuilder dataStringBuilder = new StringBuilder();
        for (String key : sortedKeys) {
            if (dataStringBuilder.length() > 0) {
                dataStringBuilder.append("\n");
            }
            dataStringBuilder.append(key).append("=").append(data.get(key));
        }
        String dataString = dataStringBuilder.toString();

        // 生成密钥
        byte[] secretKey = generateSecretKey(botToken);

        // 计算HMAC-SHA-256
        Mac hmac = Mac.getInstance(HMAC_ALGORITHM);
        hmac.init(new SecretKeySpec(secretKey, HMAC_ALGORITHM));
        byte[] hashBytes = hmac.doFinal(dataString.getBytes(StandardCharsets.UTF_8));

        // 转换为十六进制字符串
        return bytesToHex(hashBytes);
    }

    /**
     * 生成HMAC密钥
     */
    private static byte[] generateSecretKey(String botToken)
            throws NoSuchAlgorithmException, InvalidKeyException {
        Mac hmac = Mac.getInstance(HMAC_ALGORITHM);
        hmac.init(new SecretKeySpec("WebAppData".getBytes(StandardCharsets.UTF_8), HMAC_ALGORITHM));
        return hmac.doFinal(botToken.getBytes(StandardCharsets.UTF_8));
    }

    /**
     * 验证时间戳有效性
     */
    private static boolean isTimestampValid(long authDate) {
        long currentTime = Instant.now().getEpochSecond();
        long delta = Math.abs(currentTime - authDate);
        return delta <= MAX_TIME_DELTA_SECONDS;
    }

    /**
     * 字节数组转十六进制字符串
     */
    private static String bytesToHex(byte[] bytes) {
        StringBuilder result = new StringBuilder();
        for (byte b : bytes) {
            result.append(String.format("%02x", b));
        }
        return result.toString();
    }

    public static TGUser convertToTGUser(String initData) {
        var map = parseInitData(initData);
        var user = map.get("user");
        if (user == null) {
            return null;
        }
        return JSONUtil.toBean(user, TGUser.class);
    }

    // 示例用法
    public static void main(String[] args) {
        String botToken = "8063662098:AAF2SAbpkwBN3YoxXm8EgE-trzubDm"; // 替换为你的Bot Token
        String initData = "query_id=AAGThm1cAgAAAJOGbVzQVzED&user=%7B%22id%22%3A5845649043%2C%22first_name%22%3A%22cicicici%22%2C%22last_name%22%3A%22%22%2C%22username%22%3A%22mori112345%22%2C%22language_code%22%3A%22zh-hans%22%2C%22allows_write_to_pm%22%3Atrue%2C%22photo_url%22%3A%22https%3A%5C%2F%5C%2Ft.me%5C%2Fi%5C%2Fuserpic%5C%2F320%5C%2FSWEzEIMrl9HC5Brkt_sPTa7_R6VnCJG6GeOYII2pWVSeUDKss-dBA51VqU_SLn0L.svg%22%7D&auth_date=1752548354&signature=L7CFxqKuvZQnZ0XfXh55bTy2AcG4B0KrFlxs0NBihBMvWvtPNd9CkxciZYH7R-rG0UwGLzWjWcxwmJV7l8OuCA&hash=a7dee61b5bc059a0022b50fcb9760e719115fc4e960fc4f5a206382777ee50b8";

        var map = parseInitData(initData);
        var user = convertToTGUser(initData);

        VerificationResult result = verify(initData, botToken);
        System.out.println(result);

        if (result.isSuccess()) {
            System.out.println("Valid data: " + result.getData());
        }
    }


}